package com.app.demo.satoken;

import cn.dev33.satoken.annotation.SaCheckOr;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.app.core.mvc.result.Result;
import com.app.core.security.Principal;
import com.app.core.security.ResourceOwnerContext;
import com.app.core.security.ResourceOwnerService;
import com.app.demo.service.UserService;
import com.app.logger.model.Logger;
import com.app.logger.model.LoggerType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author qiangt
 * @date 2023/9/13
 * @apiNote
 */
@Slf4j
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class SaTokenController {

    private final UserService service;
    private final ResourceOwnerService resourceOwnerService;

    private final ResourceOwnerContext resourceOwnerContext;

    // 测试登录，浏览器访问： http://localhost:8081/user/doLogin?username=zhang&password=123456
    @Logger(value = "登录", type = LoggerType.LOGIN)
    @RequestMapping("doLogin")
    public Result<String> doLogin(String username, HttpServletResponse response) {
        Principal principal = resourceOwnerService.loadResourceOwner(username);
        resourceOwnerContext.setPrincipal(principal);
        return Result.success(StpUtil.getTokenValue());
    }

    // 查询登录状态，浏览器访问： http://localhost:8081/user/isLogin
    @RequestMapping("isLogin")
    public String isLogin() {
        return "当前会话是否登录：" + StpUtil.isLogin();
    }

    @RequestMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }

    // 测试注销  ---- http://localhost:8081/acc/logout
    @RequestMapping("logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }

    @RequestMapping("permissions")
    public Result permissions() {
        // 获取：当前账号所拥有的权限集合
        List<String> permissionList = StpUtil.getPermissionList();
        log.info("当前账号所拥有的permissions : {}", permissionList);

        // 判断：当前账号是否含有指定权限, 返回 true 或 false
        boolean hasPermission = StpUtil.hasPermission("user.add");
        log.info("当前账号是否含有user.add权限 : {}", hasPermission);

        // 校验：当前账号是否含有指定权限, 如果验证未通过，则抛出异常: NotPermissionException
        try {
            StpUtil.checkPermission("user.add33");
        } catch (Exception e) {
            log.error("{}，无权限user.add33", e.getClass().getSimpleName());
        }

        // 校验：当前账号是否含有指定权限 [指定多个，必须全部验证通过]
        try {
            StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get");
        } catch (Exception e) {
            log.error("{}，checkPermissionAnd校验失败", e.getClass().getSimpleName());
        }

        // 校验：当前账号是否含有指定权限 [指定多个，只要其一验证通过即可]
        try {
            StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");
        } catch (Exception e) {
            log.error("{}，checkPermissionOr校验失败", e.getClass().getSimpleName());
        }

        return Result.success();

    }

    @RequestMapping("roles")
    public Result roles() {
        // 获取：当前账号所拥有的角色集合
        List<String> roleList = StpUtil.getRoleList();
        log.info("当前账号所拥有的roleList : {}", roleList);

        // 判断：当前账号是否拥有指定角色, 返回 true 或 false
        boolean hasRole = StpUtil.hasRole("super-admin");
        log.info("当前账号是否含有super-admin权限 : {}", hasRole);


        // 校验：当前账号是否含有指定角色标识, 如果验证未通过，则抛出异常: NotRoleException
        try {
            StpUtil.checkRole("super-admin33");
        } catch (Exception e) {
            log.error("{}，无角色super-admin33", e.getClass().getSimpleName());
        }

        // 校验：当前账号是否含有指定角色标识 [指定多个，必须全部验证通过]
        // NotPermissionException
        try {
            StpUtil.checkRoleAnd("super-admin", "shop-admin");
        } catch (Exception e) {
            log.error("{}，checkRoleAnd校验失败", e.getClass().getSimpleName());
        }

        // 校验：当前账号是否含有指定角色标识 [指定多个，只要其一验证通过即可]
        try {
            StpUtil.checkRoleOr("super-admin", "shop-admin");
        } catch (Exception e) {
            log.error("{}，checkRoleAnd校验失败", e.getClass().getSimpleName());
        }

        return Result.success();

    }

    @SaCheckRole(value = {"super-admin", "super-admin33"}, mode = SaMode.AND)
    @RequestMapping("saCheckRoleAnd")
    public Result saCheckRoleAnd() {
        return Result.success();
    }

    @SaCheckRole(value = {"super-admin", "super-admin33"}, mode = SaMode.OR)
    @RequestMapping("saCheckRoleOr")
    public Result saCheckRoleOr() {
        return Result.success();
    }

    @SaCheckPermission(value = {"user.add", "user.add33"}, mode = SaMode.AND)
    @RequestMapping("saCheckPermissionAnd")
    public Result saCheckPermissionAnd() {
        return Result.success();
    }

    @SaCheckPermission(value = {"user.add", "user.add33"}, mode = SaMode.OR)
    @RequestMapping("saCheckPermissionOr")
    public Result saCheckPermissionOr() {
        return Result.success();
    }

    @SaCheckRole(value = {"super-admin"})
    @SaCheckPermission(value = {"user.add"})
    @RequestMapping("saCheckPermissionAndRole")
    public Result saCheckPermissionAndRole() {
        return Result.success();
    }

    @SaCheckOr(
            role = @SaCheckRole(value = {"super-admin33"}),
            permission = @SaCheckPermission(value = {"user.add"})
    )
    @RequestMapping("saCheckPermissionOrRole")
    public Result saCheckPermissionOrRole() {
        return Result.success();
    }

    @RequestMapping("sessions/userInfo")
    public Result<Principal> getUserInfo() {
        Principal principal = resourceOwnerContext.getPrincipal();
        return Result.success(principal);
    }

}
